using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Instances.Contracts;
using WhsFacebook.Net.Contracts;
using WhsFacebook.Net.Web.Database;
using WhsFacebook.Whs;
using ErrorInfo = Instances.Contracts.ErrorInfo;
using LatestVersionQuery = Instances.Contracts.LatestVersionQuery;
using ReleaseInfo = Instances.Contracts.ReleaseInfo;

namespace WhsFacebook.Net.Web.Services
{
    partial class WhsFacebookService
    {
        public void UpdateSystemInfo(WhsSystemInfo info)
        {
            if (info == null)
                throw new ArgumentNullException("info");

            try
            {
                using (var c = new WhsFacebookEntities())
                {
                    c.AddToUserSystemInfos(info.ToDatabase());

                    c.SaveChanges();

                    c.UpdateSystemInfosForUser(info.InstanceId);
                }
            }
            catch (Exception x)
            {
                _log.Error("Failed to add system information", x);

                throw;
            }
        }

        public void UpdateInstalledAddins(Guid instanceId, IEnumerable<WhsAddinInfo> addins)
        {
            if (instanceId == Guid.Empty)
                throw new ArgumentException("instance id is invalid/empty", "instanceId");

            if (addins == null)
                throw new ArgumentNullException("addins");

            try
            {
                using (var c = new WhsFacebookEntities())
                {
                    var pos = -1;

                    foreach (var a in addins)
                    {
                        c.AddToUserInstalledAddins(new DbUserInstalledAddin()
                        {
                            InstanceId = instanceId,
                            ListIndex = (++pos),
                            Author = a.Author,
                            ProductCode = a.ProductCode,
                            Title = a.Title,
                            Version = a.Version,
                            Submission = DateTime.UtcNow,
                        });
                    }

                    c.SaveChanges();

                    c.UpdateInstalledAddinsForUser(instanceId);
                }
            }
            catch (Exception x)
            {
                _log.Error("Failed to add add-in information", x);

                throw;
            }
        }

        public void UpdateStorageInfo(WhsStorageInfo info)
        {
            if (info == null)
                throw new ArgumentNullException("info");

            try
            {
                using (var c = new WhsFacebookEntities())
                {
                    c.AddToUserStorageInfos(info.ToDatabase());

                    c.SaveChanges();

                    c.UpdateStorageInfosForUser(info.InstanceId);
                }
            }
            catch (Exception x)
            {
                _log.Error("Failed to add storage information", x);

                throw;
            }
        }

        public void UpdateDisks(Guid instanceId, IEnumerable<WhsDiskInfo> disks)
        {
            if (instanceId == Guid.Empty)
                throw new ArgumentException("instance id is invalid/empty", "instanceId");

            if (disks == null)
                throw new ArgumentNullException("disks");

            try
            {
                using (var c = new WhsFacebookEntities())
                {
                    var pos = -1;

                    foreach (var a in disks)
                    {
                        c.AddToUserDiskInfos(new DbUserDiskInfo()
                        {
                            InstanceId = instanceId,
                            ListIndex = (++pos),
                            Submission = DateTime.UtcNow,
                            BusType = a.BusType,
                            Capacity = a.Capacity,
                            DiskId = a.DiskId,
                            DiskModel = a.DiskModel,
                            DiskRole = a.DiskRole,
                            FreeSpace = a.FreeSpace,
                            IsExternal = a.IsExternal,
                            Location = a.Location,
                            UsedSpace = a.UsedSpace,
                            WhsDiskInfoId = a.WhsDiskInfoId,
                        });
                    }

                    c.SaveChanges();

                    c.UpdateDisksForUser(instanceId);
                }
            }
            catch (Exception x)
            {
                _log.Error("Failed to add disk information", x);

                throw;
            }
        }

        public ReleaseInfo GetLatestVersion(LatestVersionQuery query)
        {
            if (query == null)
                throw new ArgumentNullException("query");

            try
            {
                using (var i = new InstancesServiceClientFactory())
                {
                    // query version
                    query.ProductId = WhsFacebookVersion.ProductId;

                    return i.CreateChannel().GetLatestVersion(query);
                }
            }
            catch (Exception x)
            {
                _log.Error("Failed to query latest version", x);

                throw;
            }
        }

        public void ReportError(ErrorInfo error)
        {
            if (error == null)
                throw new ArgumentNullException("error");

            try
            {
                using (var i = new InstancesServiceClientFactory())
                {
                    // query version
                    error.ProductId = WhsFacebookVersion.ProductId;

                    i.CreateChannel().ReportError(error);
                }
            }
            catch (Exception x)
            {
                _log.Error("Failed to report error", x);

                throw;
            }
        }

    }
}